package com.fowo.api.sys.service.impl;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.STSAssumeRoleSessionCredentialsProvider;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyuncs.exceptions.ClientException;
import com.fowo.api.sys.config.FileServiceProperties;
import com.fowo.api.sys.service.FileStorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

@ConditionalOnProperty("file-service.aliyun-oss.access-key-id")
@Service
@Slf4j
@EnableConfigurationProperties(FileServiceProperties.class)
public class AliyunOssFileStorageServiceImpl implements FileStorageService {

    @Resource
    private FileServiceProperties serviceProperties;

    public OSS createOSSClient() throws ClientException {
        final FileServiceProperties.AliyunOss aliyunOss = serviceProperties.getAliyunOss();
        String endpoint = aliyunOss.getEndpoint();
        if (!StringUtils.hasText(endpoint)) {
            endpoint = String.format("oss-%s.aliyuncs.com"
                    , aliyunOss.getRegion());
        }
        log.debug("endpoint = {}", endpoint);
        if(StringUtils.hasText(aliyunOss.getRoleArn())) {
            // 使用STSAssumeRole新建OSSClient
            final STSAssumeRoleSessionCredentialsProvider provider = CredentialsProviderFactory.newSTSAssumeRoleSessionCredentialsProvider(
                    aliyunOss.getRegion(), aliyunOss.getAccessKeyId(), aliyunOss.getAccessKeySecret(), aliyunOss.getRoleArn()
            );
            ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
            return new OSSClientBuilder().build(endpoint, provider, conf);
        } else {
            return new OSSClientBuilder().build(endpoint, aliyunOss.getAccessKeyId(), aliyunOss.getAccessKeySecret());
        }
    }

    @Override
    public String write(String filename, boolean useFilenameAsKey, InputStream inputStream) throws Exception {
        String storageKey = useFilenameAsKey ? filename : createStorageKey(filename);
        OSS oss = createOSSClient();
        try {
            oss.putObject(new PutObjectRequest(serviceProperties.getAliyunOss().getBucketName(), storageKey, inputStream));
        }
        finally {
            oss.shutdown();
        }
        return storageKey;
    }

    @Override
    public InputStream read(String storageKey) throws Exception {
        OSS oss = createOSSClient();
        try {
            final OSSObject ossObject = oss.getObject(
                    serviceProperties.getAliyunOss().getBucketName(),
                    storageKey
            );
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            StreamUtils.copy(ossObject.getObjectContent(), out);
            return new ByteArrayInputStream(out.toByteArray());
        }
        finally {
            oss.shutdown();
        }
    }

    @Override
    public void delete(String storageKey) throws Exception {
        OSS oss = createOSSClient();
        try {
            oss.deleteObject(
                    serviceProperties.getAliyunOss().getBucketName(),
                    storageKey
            );
        }
        finally {
            oss.shutdown();
        }
    }
}
